Django documentation

User authentication in Django

Django comes with a user authentication system. It handles user accounts, groups, permissions and cookie-based user sessions. This document explains how things work.

The basics

Django supports authentication out of the box. The django-admin.py init command, used to initialize a database with Django's core database tables, creates the infrastructure for the auth system. You don't have to do anything else to use authentication.

The auth system consists of:

  • Users
  • Permissions: Binary (yes/no) flags designating whether a user may perform a certain task.
  • Groups: A generic way of applying labels and permissions to more than one user.
  • Messages: A simple way to queue messages for given users.

Users

Users are represented by a standard Django model, which lives in django/models/auth.py.

API reference

Fields

User objects have the following fields:

  • username -- Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores).
  • first_name -- Optional. 30 characters or fewer.
  • last_name -- Optional. 30 characters or fewer.
  • email -- Optional. E-mail address.
  • password -- Required. A hash of, and metadata about, the password. (Django doesn't store the raw password.) Raw passwords can be arbitrarily long and can contain any character. See the "Passwords" section below.
  • is_staff -- Boolean. Designates whether this user can access the admin site.
  • is_active -- Boolean. Designates whether this user can log into the Django admin. Set this to False instead of deleting accounts.
  • is_superuser -- Boolean. Designates that this user has all permissions without explicitly assigning them.
  • last_login -- A datetime of the user's last login. Is set to the current date/time by default.
  • date_joined -- A datetime designating when the account was created. Is set to the current date/time by default when the account is created.

Methods

User objects have two many-to-many fields: groups and user_permissions. Because of those relationships, User objects get data-access methods like any other Django model:

  • get_group_list(**kwargs)
  • set_groups(id_list)
  • get_permission_list(**kwargs)
  • set_user_permissions(id_list)

In addition to those automatic API methods, User objects have the following methods:

  • is_anonymous() -- Always returns False. This is a way of comparing User objects to anonymous users.
  • get_full_name() -- Returns the first_name plus the last_name, with a space in between.
  • set_password(raw_password) -- Sets the user's password to the given raw string, taking care of the MD5 hashing. Doesn't save the User object.
  • check_password(raw_password) -- Returns True if the given raw string is the correct password for the user.
  • get_group_permissions() -- Returns a list of permission strings that the user has, through his/her groups.
  • get_all_permissions() -- Returns a list of permission strings that the user has, both through group and user permissions.
  • has_perm(perm) -- Returns True if the user has the specified permission, where perm is in the format "package.codename".
  • has_perms(perm_list) -- Returns True if the user has each of the specified permissions, where each perm is in the format "package.codename".
  • has_module_perms(package_name) -- Returns True if the user has any permissions in the given package (the Django app label).
  • get_and_delete_messages() -- Returns a list of Message objects in the user's queue and deletes the messages from the queue.
  • email_user(subject, message, from_email=None) -- Sends an e-mail to the user. If from_email is None, Django uses the DEFAULT_FROM_EMAIL setting.
  • get_profile() -- Returns a site-specific profile for this user. Raises django.models.auth.SiteProfileNotAvailable if the current site doesn't allow profiles.

Module functions

The django.models.auth.users module has the following helper functions:

  • create_user(username, email, password) -- Creates, saves and returns a User. The username, email and password are set as given, and the User gets is_active=True.
  • make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789') -- Returns a random password with the given length and given string of allowed characters. (Note that the default value of allowed_chars doesn't contain "I" or letters that look like it, to avoid user confusion.

Basic usage

Creating users

The most basic way to create users is to use the standard Django database API. Just create and save a User object:

>>> from django.models.auth import users
>>> import md5
>>> p = md5.new('johnpassword').hexdigest()
>>> u = users.User(username='john', first_name='John', last_name='lennon',
...     email='lennon@thebeatles.com', password_md5=p, is_staff=True,
...     is_active=True, is_superuser=False)
>>> u.save()

Note that password_md5 requires the raw MD5 hash (as created by md5.new().hexdigest()). Because that's a pain, there's a create_user helper function:

>>> from django.models.auth import users
>>> u = users.create_user('john', 'lennon@thebeatles.com', 'johnpassword')

Changing passwords

Change a password with set_password():

>>> from django.models.auth import users
>>> u = users.get_object(username__exact='john')
>>> u.set_password('new password')
>>> u.save()

Passwords

This only applies to the Django development version. Previous versions, such as Django 0.90, used simple MD5 hashes without password salts.

The password field of a User object is a string in this format:

hashtype$salt$hash

That's hashtype, salt and hash, separated by the dollar-sign character.

Hashtype is either sha1 (default) or md5. Salt is a random string used to salt the raw password to create the hash.

For example:

sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4

The User.set_password() and User.check_password() functions handle the setting and checking of these values behind the scenes.

Anonymous users

django.parts.auth.anonymoususers.AnonymousUser is a class that implements the django.models.auth.users.User interface, with these differences:

  • id is always None.
  • is_anonymous() returns True instead of False.
  • has_perm() always returns False.
  • set_password(), check_password(), set_groups() and set_permissions() raise NotImplementedError.

In practice, you probably won't need to use AnonymousUser objects on your own, but they're used by Web requests, as explained in the next section.

Authentication in Web requests

Until now, this document has dealt with the low-level APIs for manipulating authentication-related objects. On a higher level, Django hooks this authentication framework into its system of request objects.

In any Django view, request.user will give you a User object representing the currently logged-in user. If a user isn't currently logged in, request.user will be set to an instance of AnonymousUser (see the previous section). You can tell them apart with is_anonymous(), like so:

if request.user.is_anonymous():
    # Do something for anonymous users.
else:
    # Do something for logged-in users.

If you want to use request.user in your view code, make sure you have SessionMiddleware enabled. See the session documentation for more information.

Limiting access to logged-in users

The raw way

The simple, raw way to limit access to pages is to check request.user.is_anonymous() and either redirect to a login page:

from django.utils.httpwrappers import HttpResponseRedirect

def my_view(request):
    if request.user.is_anonymous():
        return HttpResponseRedirect('/login/?next=%s' % request.path)
    # ...

...or display an error message:

def my_view(request):
    if request.user.is_anonymous():
        return render_to_response('myapp/login_error')
    # ...

The login_required decorator

As a shortcut, you can use the convenient login_required decorator:

from django.views.decorators.auth import login_required

def my_view(request):
    # ...
my_view = login_required(my_view)

Here's the same thing, using Python 2.4's decorator syntax:

from django.views.decorators.auth import login_required

@login_required
def my_view(request):
    # ...

login_required does the following:

  • If the user isn't logged in, redirect to /accounts/login/, passing the current absolute URL in the query string as next. For example: /accounts/login/?next=/polls/3/.
  • If the user is logged in, execute the view normally. The view code is free to assume the user is logged in.

Limiting access to logged-in users that pass a test

To limit access based on certain permissions or some other test, you'd do essentially the same thing as described in the previous section.

The simple way is to run your test on request.user in the view directly. For example, this view checks to make sure the user is logged in and has the permission polls.can_vote:

def my_view(request):
    if request.user.is_anonymous() or not request.user.has_perm('polls.can_vote'):
        return HttpResponse("You can't vote in this poll.")
    # ...

As a shortcut, you can use the convenient user_passes_test decorator:

from django.views.decorators.auth import user_passes_test

def my_view(request):
    # ...
my_view = user_passes_test(my_view, lambda u: u.has_perm('polls.can_vote'))

Here's the same thing, using Python 2.4's decorator syntax:

from django.views.decorators.auth import user_passes_test

@user_passes_test(lambda u: u.has_perm('polls.can_vote'))
def my_view(request):
    # ...

user_passes_test takes a required argument: a callable that takes a User object and returns True if the user is allowed to view the page. Note that user_passes_test does not automatically check that the User is not anonymous.

Limiting access to generic views

To limit access to a generic view, write a thin wrapper around the view, and point your URLconf to your wrapper instead of the generic view itself. For example:

from django.views.generic.date_based import object_detail

@login_required
def limited_object_detail(*args, **kwargs):
    return object_detail(*args, **kwargs)

Permissions

Django comes with a simple permissions system. It provides a way to assign permissions to specific users and groups of users.

It's used by the Django admin site, but you're welcome to use it in your own code.

The Django admin site uses permissions as follows:

  • Access to view the "add" form and add an object is limited to users with the "add" permission for that type of object.
  • Access to view the change list, view the "change" form and change an object is limited to users with the "change" permission for that type of object.
  • Access to delete an object is limited to users with the "delete" permission for that type of object.

Permissions are set globally per type of object, not per specific object instance. For example, it's possible to say "Mary may change news stories," but it's not currently possible to say "Mary may change news stories, but only the ones she created herself" or "Mary may only change news stories that have a certain status or publication date." The latter functionality is something Django developers are currently discussing.

Default permissions

Three basic permissions -- add, create and delete -- are automatically created for each Django model that has admin set. Behind the scenes, these permissions are added to the auth_permissions database table when you run django-admin.py install [app]. You can view the exact SQL INSERT statements by running django-admin.py sqlinitialdata [app].

Note that if your model doesn't have admin set when you run django-admin.py install, the permissions won't be created. If you initialize your database and add admin to models after the fact, you'll need to add the permissions to the database manually. Do this by running django-admin.py installperms [app], which creates any missing permissions for the given app.

Custom permissions

To create custom permissions for a given model object, use the permissions model META attribute.

This example model creates three custom permissions:

class USCitizen(meta.Model):
    # ...
    class META:
        permissions = (
            ("can_drive", "Can drive"),
            ("can_vote", "Can vote in elections"),
            ("can_drink", "Can drink alcohol"),
        )

API reference

Just like users, permissions are implemented in a Django model that lives in django/models/auth.py.

Fields

Permission objects have the following fields:

  • name -- Required. 50 characters or fewer. Example: 'Can vote'.
  • package -- Required. A reference to the packages database table, which contains a record for each installed Django application.
  • codename -- Required. 100 characters or fewer. Example: 'can_vote'.

Methods

Permission objects have the standard data-access methods like any other Django model:

Authentication data in templates

The currently logged-in user and his/her permissions are made available in the template context when you use DjangoContext.

Users

The currently logged-in user, either a User object or an``AnonymousUser`` instance, is stored in the template variable {{ user }}:

{% if user.is_anonymous %}
    <p>Welcome, new user. Please log in.</p>
{% else %}
    <p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% endif %}

Permissions

The currently logged-in user's permissions are stored in the template variable {{ perms }}. This is an instance of django.core.extensions.PermWrapper, which is a template-friendly proxy of permissions.

In the {{ perms }} object, single-attribute lookup is a proxy to User.has_module_perms. This example would display True if the logged-in user had any permissions in the foo app:

{{ perms.foo }}

Two-level-attribute lookup is a proxy to User.has_perm. This example would display True if the logged-in user had the permission foo.can_vote:

{{ perms.foo.can_vote }}

Thus, you can check permissions in template {% if %} statements:

{% if perms.foo %}
    <p>You have permission to do something in the foo app.</p>
    {% if perms.foo.can_vote %}
        <p>You can vote!</p>
    {% endif %}
    {% if perms.foo.can_drive %}
        <p>You can drive!</p>
    {% endif %}
{% else %}
    <p>You don't have permission to do anything in the foo app.</p>
{% endif %}

Groups

Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups.

A user in a group automatically has the permissions granted to that group. For example, if the group Site editors has the permission can_edit_home_page, any user in that group will have that permission.

Beyond permissions, groups are a convenient way to categorize users to apply some label, or extended functionality, to them. For example, you could create a group 'Special users', and you could write code that would do special things to those users -- such as giving them access to a members-only portion of your site, or sending them members-only e-mail messages.

Messages

The message system is a lightweight way to queue messages for given users.

A message is associated with a User. There's no concept of expiration or timestamps.

Messages are used by the Django admin after successful actions. For example, "The poll Foo was created successfully." is a message.

The API is simple:

* To add messages, use ``user.add_message(message_text)``.
* To retrieve/delete messages, use ``user.get_and_delete_messages()``,
  which returns a list of ``Message`` objects in the user's queue (if any)
  and deletes the messages from the queue.

In this example view, the system saves a message for the user after creating a playlist:

def create_playlist(request, songs):
    # Create the playlist with the given songs.
    # ...
    request.user.add_message("Your playlist was added successfully.")
    return render_to_response("playlists/create", context_instance=DjangoContext(request))

When you use DjangoContext, the currently logged-in user and his/her messages are made available in the template context as the template variable {{ messages }}. Here's an example of template code that displays messages:

{% if messages %}
<ul>
    {% for message in messages %}
    <li>{{ message.message }}</li>
    {% endfor %}
</ul>
{% endif %}

Note that DjangoContext calls get_and_delete_messages behind the scenes, so any messages will be deleted even if you don't display them.

Finally, note that this messages framework only works with users in the user database. To send messages to anonymous users, use the session framework.

Comments

leftwing November 10, 2005 at 10:52 a.m.

Great documentation, thanks, this will help.

Is there a reason that login_required always redirects to a hard coded location rather than taking an optional location parameter?

qk November 11, 2005 at 1:14 p.m.

Can I subclass User class and override check_password() method and still using same database table. I want to check user password against LDAP server, so users don't need to create a new password for my application.

mike November 15, 2005 at 3:17 p.m.

I'm also interested in authenticating users via LDAP and in some cases PAM.

Chris November 21, 2005 at 2:48 p.m.

Yes, LDAP would be very nice. Maybe store permissions, roles, in the database, Users and groups pull from LDAP.

Peter of the Norse November 23, 2005 at 10:41 p.m.

Is there a way to add more information to the User table? I want to save phone numbers and preference settings, and I'd rather not use a second table if possible.

Post a comment

Note: Please only use the comments for questions/critcisms/suggestions on the docs; if you experience errors please file a ticket, ask in the IRC channel, or post to the django-users list. Comments will be periodically reviewed, integrated into the documentation proper, and removed.

Your name:

Comment: